package com.wanban.download

import android.app.Application
import android.app.ForegroundServiceStartNotAllowedException
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Build
import android.os.IBinder
import android.text.TextUtils
import android.util.Log
import com.wanban.download.db.DatabaseManager
import com.wanban.download.db.DownloadEntity
import com.wanban.download.listener.OnLoadCoverImageListener
import com.wanban.download.model.DownloadType
import com.wanban.download.model.Status
import com.wanban.download.service.DownloadService
import com.wanban.download.utils.CacheM3U8Utils
import com.wanban.download.utils.NetworkUtils
import com.wanban.download.utils.PathUtils
import com.wanban.download.utils.RxJavaUtils
import com.wanban.download.utils.VideoDownloadSPUtil
import io.reactivex.Flowable
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.io.File
import java.util.concurrent.TimeUnit


/**
 * 下载器入口
 * 视频下载器：支持m3u8和mp4格式视频下载，并支持断点续传功能，同时允许切换多种下载器进行下载（注：
 * 目前只支持默认和腾讯下载器）。
 */
object WBDownloadUtils : NetworkUtils.OnNetworkStatusChangedListener {

    const val TAG = "NewVideoDownload"
    private var downloadService: DownloadService? = null
    private var serviceDisposable: Disposable? = null
    private var bindServiceDisposable: Disposable? = null

    private val connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            val binder = service as DownloadService.LocalBinder
            downloadService = binder.getService()
            Log.e("DownloadService", "onServiceConnected -> 下载服务已绑定~")
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            Log.e("DownloadService", "下载服务取消绑定~")
            downloadService = null
        }
    }

    internal val downloadManager by lazy { DefaultDownloadManager() }
    private var isInitializer = false

    private fun hasDownloadTaskRunning() {
        if (serviceDisposable == null) {
            serviceDisposable = Flowable.interval(1, TimeUnit.MINUTES)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    val hasAvailableTask = getUnSuccessTasks().isNotEmpty()
                    Log.d("DownloadService", "检查是否有可用任务 -> ${hasAvailableTask}...")
                    if (!hasAvailableTask) {
                        unbindDownloadService()
                    }
                }, {
                    it?.printStackTrace()
                })
        }
    }

    fun init(application: Application, callback: (tasks: ArrayList<DownloadEntity>) -> Unit): WBDownloadUtils {
        NetworkUtils.registerNetworkStatusChangedListener(this)
        // 初始化数据库
        initDataManager(application)

        // 绑定服务
        bindDownloadService()

        // 查询数据表
        Observable.create {
            // 从数据库获取所有的任务
            val tasks = DatabaseManager.getInstance()?.getTasks(isContainerM3U8 = true)
            // 准备删除1.1.8版本的bug导致的无法删除已下载的文件，只能删除默认下载的文件
            if (tasks.isNullOrEmpty()) {
                if (it.isDisposed) return@create
                it.onNext(ArrayList())
                return@create
            }
            var result = tasks.filter { it.state != Status.SUCCESS && it.state != Status.DELETE } as ArrayList
            for (task in result) {
                if (!DefaultDownloadManager.isTaskInRunningState(task)) continue
                // 重置下载状态
                task.state = Status.PENDING
            }
            // 排序
            result = ArrayList(result.sortedBy { it.createTime })
            it.onNext(result)
        }.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({ tasks ->
                // 初始化完成
                execDBInitialized(tasks, callback)
            }, {
                it?.printStackTrace()
                execDBInitialized(ArrayList(), callback)
            }).isDisposed
        return this
    }

    private fun execDBInitialized(tasks: ArrayList<DownloadEntity>, callback: (tasks: ArrayList<DownloadEntity>) -> Unit) {
        downloadManager.setTasks(tasks)
        isInitializer = true
        // 初始化完成
        callback(tasks)
    }

    fun initDataManager(application: Application) {
        // 初始化数据库
        DatabaseManager.initializeInstance(application)
    }

    fun initByOldManager(tasks: ArrayList<DownloadEntity>) {
        downloadManager.setTasks(tasks)
        isInitializer = true
        NetworkUtils.registerNetworkStatusChangedListener(this)
    }

    /**
     * 是否初始化完成
     */
    fun isInitializerSuccess(): Boolean {
        return isInitializer
    }

    private fun bindDownloadService() {
        if (downloadService != null) return
        // 绑定服务
        val intent = Intent(ContextProvider.application, DownloadService::class.java)
        ContextProvider.application.bindService(intent, connection, Context.BIND_AUTO_CREATE)
        // 检测如果没有下载任务就关闭服务
        hasDownloadTaskRunning()
    }

    private fun unbindDownloadService() {
        serviceDisposable?.dispose()
        serviceDisposable = null
        ContextProvider.application.unbindService(connection)
        downloadService = null

        bindServiceDisposable?.dispose()
        bindServiceDisposable = null
    }

    private fun waitDownloadServiceBinding(exc: () -> Unit) {
        bindServiceDisposable?.dispose()
        bindServiceDisposable = Flowable.interval(100, TimeUnit.MILLISECONDS)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                Log.e("DownloadService", "等待下载服务绑定...")
                if (downloadService != null) {
                    Log.e("DownloadService", "下载服务已绑定...")
                    bindServiceDisposable?.dispose()
                    bindServiceDisposable = null
                    exc()
                }
            }, {
                it?.printStackTrace()
            })
    }


    fun resumeAllDownloads() {
        // 如果没有可以启动的任务，就不在执行resumeAll
        if (downloadManager.getCanRunningTasks().isEmpty()) return
//        val intent = Intent(ContextProvider.application, DownloadService::class.java)
//        intent.putExtra(DownloadConstants.INTENT_KEY_SERVICE_ACTION, 0)
//        startService(intent) {
//            downloadManager.resumeAllDownloads()
//        }

//        bindDownloadService(ContextProvider.application)

        if (downloadService == null) { // 需要重新绑定服务
            // 绑定服务
            bindDownloadService()
            // 等待下载服务绑定完成
            waitDownloadServiceBinding {
                downloadService?.resumeAllDownloads()
            }
        } else {
            downloadService?.resumeAllDownloads()
        }
    }


    fun startDownload(task: DownloadEntity) {
//        val intent = Intent(ContextProvider.application, DownloadService::class.java)
//        intent.putExtra(DownloadConstants.INTENT_KEY_SERVICE_TASK, task)
//        intent.putExtra(DownloadConstants.INTENT_KEY_SERVICE_ACTION, 1)
//        startService(intent) {
//            downloadManager.startDownload(task)
//        }
//        bindDownloadService(ContextProvider.application)

        if (downloadService == null) { // 需要重新绑定服务
            // 绑定服务
            bindDownloadService()
            // 等待下载服务绑定完成
            waitDownloadServiceBinding {
                downloadService?.startDownload(task)
            }
        } else {
            downloadService?.startDownload(task)
        }
    }

    fun stopDownload(url: String) {
        downloadManager.stopDownload(url)
    }

    fun resumeDownload(url: String) {
//        val intent = Intent(ContextProvider.application, DownloadService::class.java)
//        intent.putExtra(DownloadConstants.INTENT_KEY_SERVICE_DOWNLOAD_URL, url)
//        intent.putExtra(DownloadConstants.INTENT_KEY_SERVICE_ACTION, 3)
//        startService(intent) {
//            downloadManager.resumeDownload(url)
//        }
//        bindDownloadService(ContextProvider.application)


        if (downloadService == null) { // 需要重新绑定服务
            // 绑定服务
            bindDownloadService()
            // 等待下载服务绑定完成
            waitDownloadServiceBinding {
                downloadService?.resumeDownload(url)
            }
        } else {
            downloadService?.resumeDownload(url)
        }
    }

    fun deleteDownload(url: String) {
        downloadManager.deleteDownload(url)
    }

    fun deleteDownloads(urls: List<DownloadEntity>, complete: () -> Unit) {
        downloadManager.deleteDownloads(urls, complete)
    }

    /**
     * 返回所有的下载任务，不包括IDLE，DELETE，SUCCESS
     */
    fun getUnSuccessTasks(): ArrayList<DownloadEntity> {
        return downloadManager.getUnSuccessTasks()
    }

    fun getSuccessTasks(complete: (tasks: ArrayList<DownloadEntity>) -> Unit) {
        return downloadManager.getSuccessTasks(complete)
    }

    /**
     * 返回当前任务栈中，可以下载的任务
     */
    fun getCanRunningTasks(): ArrayList<DownloadEntity> {
        return downloadManager.getCanRunningTasks()
    }

    /**
     * 当前任务是否能加入下载栈
     */
    fun canAddTask(url: String, complete: (canAddTask: Boolean, errorMsg: String?) -> Unit) {
        downloadManager.canAddTask(url, complete)
    }

    /**
     * 返回当前下载路径是否是用的sdcard
     */
    fun isUseSdcardDownload(): Boolean {
        return VideoDownloadSPUtil.instance.isUseSdcardDownload
    }

    /**
     * 设置是否使用sdcard下载
     */
    fun setUserSdcardDownload(isUseSdcardDownload: Boolean) {
        VideoDownloadSPUtil.instance.isUseSdcardDownload = isUseSdcardDownload
    }

    /**
     * 是否只允许wifi下载
     */
    fun isDownloadOnlyWifi(): Boolean {
        return VideoDownloadSPUtil.instance.isDownloadOnlyWIFI
    }

    /**
     * 设置是否只允许wifi下载
     */
    fun setDownloadOnlyWifi(isDownloadOnlyWifi: Boolean) {
        VideoDownloadSPUtil.instance.isDownloadOnlyWIFI = isDownloadOnlyWifi
    }

    /**
     * 设置图片缓存下载监听
     */
    fun setOnLoadCoverImageListener(onLoadCoverImageListener: OnLoadCoverImageListener?) {
        downloadManager.setOnLoadCoverImageListener(onLoadCoverImageListener)
    }

    fun getCurrentDownloadType(): Int {
        return downloadManager.getDownloadType()
    }

    fun setDownloadType(@DownloadType type: Int) {
        downloadManager.setDownloadType(type)
    }

    fun insertOrUpdateTask(task: DownloadEntity, isContainerM3U8: Boolean = false) {
        RxJavaUtils.doAsync {
            DatabaseManager.getInstance()?.insert(task, isContainerM3U8)
            return@doAsync true
        }
    }

    fun getTasks(
        selection: String?,
        selectionArgs: Array<String>?,
        isContainerM3U8: Boolean = false
    ): ArrayList<DownloadEntity>? {
        return DatabaseManager.getInstance()?.getTasks(selection, selectionArgs, isContainerM3U8)
    }

    fun deleteDownloadFiles(complete: () -> Unit) {
        RxJavaUtils.doAsync({
            // 删除文件
            val allTasks = DatabaseManager.getInstance()?.getTasks()
            if (allTasks.isNullOrEmpty()) {
                // 执行删除文件
                PathUtils.deleteAllDownloadFiles()
                return@doAsync true
            }
            // 暂停正在下载的任务
            allTasks.forEach {
                // 暂停所有正在下载的任务
                if (it.state != Status.SUCCESS) {
                    downloadManager.stopDownloadUtils(it.url)
                }
            }
            downloadManager.clear()

            Thread.sleep(2000)
            for (task in allTasks) {
                // 删除m3u8
                CacheM3U8Utils.clearCacheM3U8(task.downloadTag)
                // 删除任务文件
                if (TextUtils.isEmpty(task.fileRootPath)) {
                    continue
                }
                val file = File(task.fileRootPath)
                if (file.exists()) {
                    file.deleteRecursively()
                }
            }
            Thread.sleep(1000)
            // 删除数据库
            DatabaseManager.getInstance()?.deleteAll()
            // 执行删除文件
            PathUtils.deleteAllDownloadFiles()
            return@doAsync true
        }, {
            complete()
        }, {
            complete()
        })
    }


    override fun onDisconnected() {

    }

    private var networkDisposable: Disposable? = null
    override fun onConnected(networkType: NetworkUtils.NetworkType?) {
        networkDisposable?.dispose()
        networkDisposable = RxJavaUtils.delay(5000) { // 延迟5s启动，防止网络处于connecting
            downloadManager.resumeFromNetworkConnected()
            networkDisposable?.dispose()
            networkDisposable = null
        }

    }

    // 启动服务，如果启动失败，直接调用下载方法
    private fun startService(intent: Intent, tryCatch: () -> Unit) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                try {
                    ContextProvider.application.startForegroundService(intent)
                } catch (e: ForegroundServiceStartNotAllowedException) {
                    e.printStackTrace()
                    tryCatch()
                } catch (e: Exception) {
                    e.printStackTrace()
                    tryCatch()
                }
            } else {
                try {
                    ContextProvider.application.startForegroundService(intent)
                } catch (e: Exception) {
                    e.printStackTrace()
                    tryCatch()
                }
            }
        } else {
            try {
                ContextProvider.application.startService(intent)
            } catch (e: Exception) {
                e.printStackTrace()
                tryCatch()
            }
        }
    }
}